package com.aizuda.boot.modules.business.performance.service.impl;

import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.business.contract.entity.ContractTypeEntity;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.filling.domain.request.PageQuery;
import com.aizuda.boot.modules.business.performance.domain.entity.ContractPerformanceEntity;
import com.aizuda.boot.modules.business.performance.domain.entity.ContractPerformanceTypeEntity;
import com.aizuda.boot.modules.business.performance.domain.request.SavePerformanceDTO;
import com.aizuda.boot.modules.business.performance.domain.request.UpdatePerformanceDTO;
import com.aizuda.boot.modules.business.performance.domain.response.PerformanceShowDTO;
import com.aizuda.boot.modules.business.performance.domain.response.PerformanceShowListDTO;
import com.aizuda.boot.modules.common.constant.enums.PerformanceMethodEnum;
import com.aizuda.boot.modules.common.constant.enums.PerformanceObjectEnum;
import com.aizuda.boot.modules.common.constant.enums.PerformanceTimeEnum;
import com.aizuda.boot.modules.business.performance.mapper.ContractPerformanceMapper;
import com.aizuda.boot.modules.business.performance.mapper.ContractPerformanceTypeMapper;
import com.aizuda.boot.modules.business.performance.mapper.ContractTypeMapper;
import com.aizuda.boot.modules.business.performance.service.ContractPerformanceService;
import com.aizuda.boot.modules.business.permission.domain.response.EmployeeShowVO;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author sangyirong
 * @ClassName ContractPerformanceServiceImpl
 * @Version 1.0
 * @Date 2025/6/4 16:37
 */
@Service
@Slf4j
public class ContractPerformanceServiceImpl extends ServiceImpl<ContractPerformanceMapper, ContractPerformanceEntity> implements ContractPerformanceService {

    @Resource
    private ContractPerformanceMapper contractPerformanceMapper;

    @Resource
    private ContractPerformanceTypeMapper contractPerformanceTypeMapper;

    @Resource
    private ContractTypeMapper contractTypeMapper;

    @Resource
    private ISysUserService sysUserService;


    /**
     * 创建履约提醒
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> createPerformance(SavePerformanceDTO dto) {
        try {
            UserInfo currentUser = AuthUtil.getCurrentUser();
            if (Objects.isNull(currentUser.getEmployeeId())) {
                return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
            }

            // 数据校验
            if (Objects.isNull(dto) || Objects.isNull(dto.getPerformanceType()) || StringUtils.isEmpty(dto.getPerformanceName())
                    || CollectionUtils.isEmpty(dto.getContractTypeIds()) || CollectionUtils.isEmpty(dto.getPerformanceTime()) || CollectionUtils.isEmpty(dto.getPerformanceObject())) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            long count = contractPerformanceMapper.selectCount(new LambdaQueryWrapper<ContractPerformanceEntity>()
                    .eq(ContractPerformanceEntity::getPerformanceName, dto.getPerformanceName()));
            if (count > 0) {
                return SingleResponse.failure(ResponseCodeEnum.DATA_ALREADY_EXISTS.getCode(), "履约提醒名称重复");
            }

            // 创建实体赋值
            ContractPerformanceEntity contractPerformanceEntity = new ContractPerformanceEntity();
            contractPerformanceEntity.setPerformanceType(dto.getPerformanceType());
            contractPerformanceEntity.setPerformanceName(dto.getPerformanceName());
            String performanceTime = dto.getPerformanceTime().stream().map(PerformanceTimeEnum::getCode).collect(Collectors.joining(","));
            contractPerformanceEntity.setPerformanceTime(performanceTime);
            if (dto.getPerformanceTime().contains(PerformanceTimeEnum.BEFORE_DUE_DATE)) {
                contractPerformanceEntity.setPerformanceDay(dto.getPerformanceDay());
            }
            String performanceObjet = dto.getPerformanceObject().stream().map(PerformanceObjectEnum::getCode).collect(Collectors.joining(","));
            contractPerformanceEntity.setPerformanceObject(performanceObjet);
            if (dto.getPerformanceObject().contains(PerformanceObjectEnum.SPECIFIED_PERSON)) {
                String collect = dto.getPerformanceUser().stream().map(String::valueOf).collect(Collectors.joining(","));
                contractPerformanceEntity.setPerformanceUser(collect);
            }
            contractPerformanceEntity.setPerformanceMethod(null == dto.getPerformanceMethod() ? PerformanceMethodEnum.FEISHU : dto.getPerformanceMethod());
            contractPerformanceMapper.insert(contractPerformanceEntity);

            // 保存合同类型范围
            scopeSave(dto.getContractTypeIds(), contractPerformanceEntity.getId());

            return SingleResponse.success();
        } catch (Exception e) {
            log.error("创建履约提醒失败", e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "创建履约提醒失败：" + e.getMessage());
        }
    }

    /**
     * 获取履约提醒
     *
     * @param id
     * @return
     */
    @Override
    public SingleResponse<PerformanceShowDTO> getPerformance(Integer id) {
        try {
            // 参数校验
            if (Objects.isNull(id)) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            ContractPerformanceEntity contractPerformanceEntity = contractPerformanceMapper.selectById(id);
            if (Objects.isNull(contractPerformanceEntity)) {
                return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
            }

            // 赋值
            PerformanceShowDTO performanceShowDTO = new PerformanceShowDTO();
            performanceShowDTO.setId(contractPerformanceEntity.getId());
            performanceShowDTO.setPerformanceType(contractPerformanceEntity.getPerformanceType());
            performanceShowDTO.setPerformanceName(contractPerformanceEntity.getPerformanceName());
            List<PerformanceTimeEnum> performanceTime = Arrays.stream(contractPerformanceEntity.getPerformanceTime().split(",")).map(PerformanceTimeEnum::valueOf).collect(Collectors.toList());
            performanceShowDTO.setPerformanceTime(performanceTime);
            if (performanceTime.contains(PerformanceTimeEnum.BEFORE_DUE_DATE)) {
                performanceShowDTO.setPerformanceDay(contractPerformanceEntity.getPerformanceDay());
            }
            List<PerformanceObjectEnum> performanceObject = Arrays.stream(contractPerformanceEntity.getPerformanceObject().split(",")).map(PerformanceObjectEnum::valueOf).collect(Collectors.toList());
            performanceShowDTO.setPerformanceObject(performanceObject);
            if (performanceObject.contains(PerformanceObjectEnum.SPECIFIED_PERSON)) {
                String[] split = contractPerformanceEntity.getPerformanceUser().split(",");
                performanceShowDTO.setPerformanceUser(Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList()));
            }
            performanceShowDTO.setPerformanceMethod(contractPerformanceEntity.getPerformanceMethod());

            // 范围
            List<Integer> TypeIds = contractPerformanceTypeMapper.selectList(new LambdaQueryWrapper<ContractPerformanceTypeEntity>()
                            .eq(ContractPerformanceTypeEntity::getPerformanceId, id))
                    .stream().map(ContractPerformanceTypeEntity::getContractTypeId).collect(Collectors.toList());
            performanceShowDTO.setContractTypeIds(TypeIds);

            return SingleResponse.of(performanceShowDTO);
        } catch (Exception e) {
            log.error("获取履约提醒详情失败，ID: {}", id, e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "获取履约提醒详情失败：" + e.getMessage());
        }
    }

    /**
     * 更新履约提醒
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> updatePerformance(UpdatePerformanceDTO dto) {
        try {
            UserInfo currentUser = AuthUtil.getCurrentUser();
            if (Objects.isNull(currentUser.getEmployeeId())) {
                return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
            }

            //  参数校验
            if (Objects.isNull(dto) || Objects.isNull(dto.getId()) || StringUtils.isEmpty(dto.getPerformanceName()) || CollectionUtils.isEmpty(dto.getContractTypeIds())
                    || Objects.isNull(dto.getPerformanceType()) || Objects.isNull(dto.getPerformanceTime()) || Objects.isNull(dto.getPerformanceObject())) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            ContractPerformanceEntity contractPerformanceEntity = contractPerformanceMapper.selectById(dto.getId());
            if (Objects.isNull(contractPerformanceEntity)) {
                return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
            }

            long count = contractPerformanceMapper.selectCount(new LambdaQueryWrapper<ContractPerformanceEntity>()
                    .ne(ContractPerformanceEntity::getId, dto.getId())
                    .eq(ContractPerformanceEntity::getPerformanceName, dto.getPerformanceName()));
            if (count > 0) {
                return SingleResponse.failure(ResponseCodeEnum.DATA_ALREADY_EXISTS.getCode(), "履约提醒名称重复");
            }

            // 主表赋值
            contractPerformanceEntity.setPerformanceName(dto.getPerformanceName());
            contractPerformanceEntity.setPerformanceType(dto.getPerformanceType());
            contractPerformanceEntity.setPerformanceTime(dto.getPerformanceTime().stream().map(PerformanceTimeEnum::getCode).collect(Collectors.joining(",")));
            if (dto.getPerformanceTime().contains(PerformanceTimeEnum.BEFORE_DUE_DATE)) {
                contractPerformanceEntity.setPerformanceDay(dto.getPerformanceDay());
            }
            String performanceObjet = dto.getPerformanceObject().stream().map(PerformanceObjectEnum::getCode).collect(Collectors.joining(","));
            contractPerformanceEntity.setPerformanceObject(performanceObjet);
            if (dto.getPerformanceObject().contains(PerformanceObjectEnum.SPECIFIED_PERSON)) {
                String collect = dto.getPerformanceUser().stream().map(String::valueOf).collect(Collectors.joining(","));
                contractPerformanceEntity.setPerformanceUser(collect);
            }
            contractPerformanceEntity.setPerformanceMethod(dto.getPerformanceMethod());
            contractPerformanceMapper.updateById(contractPerformanceEntity);

            //  关联表
            contractPerformanceTypeMapper.delete(new LambdaQueryWrapper<ContractPerformanceTypeEntity>().eq(ContractPerformanceTypeEntity::getPerformanceId, dto.getId()));
            scopeSave(dto.getContractTypeIds(), dto.getId());

            return SingleResponse.success();
        } catch (Exception e) {
            log.error("更新履约提醒失败", e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "更新履约提醒失败：" + e.getMessage());
        }
    }

    private void scopeSave(List<Integer> contractTypeIds, Integer id) {
        List<ContractPerformanceTypeEntity> typeEntities = contractTypeIds.stream().map(typeId -> {
            ContractPerformanceTypeEntity contractPerformanceType = new ContractPerformanceTypeEntity();
            contractPerformanceType.setContractTypeId(typeId);
            contractPerformanceType.setPerformanceId(id);
            return contractPerformanceType;
        }).collect(Collectors.toList());
        for (ContractPerformanceTypeEntity entity : typeEntities) {
            contractPerformanceTypeMapper.insert(entity);
        }
    }

    /**
     * 删除履约提醒
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse<Void> deletePerformance(Integer id) {
        try {
            if (Objects.isNull(id)) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            if (contractPerformanceMapper.deleteById(id) <= 0) {
                return SingleResponse.failure(ResponseCodeEnum.DATA_NOT_FOUND.getCode(), ResponseCodeEnum.DATA_NOT_FOUND.getMsg());
            }

            contractPerformanceTypeMapper.delete(new LambdaQueryWrapper<ContractPerformanceTypeEntity>().eq(ContractPerformanceTypeEntity::getPerformanceId, id));

            return SingleResponse.success();
        } catch (Exception e) {
            log.error("删除履约提醒失败，ID: {}", id, e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "删除履约提醒失败：" + e.getMessage());
        }
    }

    /**
     * 获取履约提醒列表
     *
     * @param pageQuery
     * @return
     */
    @Override
    public SingleResponse<IPage<PerformanceShowListDTO>> getPerformanceList(PageQuery pageQuery) {
        try {
            UserInfo currentUser = AuthUtil.getCurrentUser();
            if (Objects.isNull(currentUser.getEmployeeId())) {
                return SingleResponse.failure(ResponseCodeEnum.NOT_LOGGED.getCode(), ResponseCodeEnum.NOT_LOGGED.getMsg());
            }

            //  参数校验
            if (Objects.isNull(pageQuery) || Objects.isNull(pageQuery.getPageNo()) || Objects.isNull(pageQuery.getPageSize())) {
                return SingleResponse.failure(ResponseCodeEnum.PARAMETER_ERROR.getCode(), ResponseCodeEnum.PARAMETER_ERROR.getMsg());
            }

            //  分页
            IPage<ContractPerformanceEntity> page = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());
            IPage<ContractPerformanceEntity> performanceEntityIPage = contractPerformanceMapper.selectPage(page,
                    new LambdaQueryWrapper<ContractPerformanceEntity>());
            List<ContractPerformanceEntity> performanceEntities = performanceEntityIPage.getRecords();

            //  获取员工信息
            TreeSet<Long> employeeIds = new TreeSet<>();
            performanceEntities.forEach(performanceEntity -> {
                List<PerformanceObjectEnum> collect = Arrays.stream(performanceEntity.getPerformanceObject().split(",")).map(PerformanceObjectEnum::valueOf).collect(Collectors.toList());
                if (collect.contains(PerformanceObjectEnum.SPECIFIED_PERSON)) {
                    List<String> performanceUser = Arrays.asList(performanceEntity.getPerformanceUser().split(","));
                    employeeIds.addAll(performanceUser.stream().map(Long::valueOf).collect(Collectors.toList()));
                }
            });
            Map<Long, EmployeeShowVO> employeeShow;
            if (!employeeIds.isEmpty()) {
                employeeShow = sysUserService.listByIds(employeeIds).stream().map(item -> {
                    EmployeeShowVO employeeShowVO = new EmployeeShowVO();
                    employeeShowVO.setId(item.getId());
                    employeeShowVO.setName(item.getNickName());
                    employeeShowVO.setAvatar(item.getAvatar());
                    return employeeShowVO;
                }).collect(Collectors.toMap(EmployeeShowVO::getId, item -> item));
            } else {
                employeeShow = null;
            }

            // 获取合同提醒id
            List<Integer> performanceIds = performanceEntities.stream().map(ContractPerformanceEntity::getId).collect(Collectors.toList());
            // 获取范围映射
            Map<Integer, List<String>> scopeMap = new HashMap<>();
            if (!performanceIds.isEmpty()) {
                List<ContractPerformanceTypeEntity> performanceTypeEntities = contractPerformanceTypeMapper.selectList(new LambdaQueryWrapper<ContractPerformanceTypeEntity>()
                        .in(ContractPerformanceTypeEntity::getPerformanceId, performanceIds));
                // 获取合同类型id
                List<Integer> contractTypeIds = performanceTypeEntities.stream().map(ContractPerformanceTypeEntity::getContractTypeId).collect(Collectors.toList());
                // 查询合同类型信息
                Map<Integer, String> typeMap;
                if (!contractTypeIds.isEmpty()) {
                    typeMap = contractTypeMapper.selectList(new LambdaQueryWrapper<ContractTypeEntity>()
                                    .in(ContractTypeEntity::getId, contractTypeIds))
                            .stream().collect(Collectors.toMap(ContractTypeEntity::getId, ContractTypeEntity::getTypeName));
                } else {
                    typeMap = new HashMap<>();
                }
                // 构建映射
                Map<Integer, List<ContractPerformanceTypeEntity>> collect = performanceTypeEntities.stream().collect(Collectors.groupingBy(ContractPerformanceTypeEntity::getPerformanceId));
                collect.forEach((performanceId, performanceTypeEntityList) -> {
                    List<String> typeNames = performanceTypeEntityList.stream().map(performanceTypeEntity -> typeMap.get(performanceTypeEntity.getContractTypeId())).collect(Collectors.toList());
                    scopeMap.put(performanceId, typeNames);
                });
            }

            // 构造结果集
            List<PerformanceShowListDTO> performanceShowListDTOS = performanceEntities.stream()
                    .map(performanceEntity -> {
                        //赋值构造结果
                        PerformanceShowListDTO performanceShowListDTO = new PerformanceShowListDTO();
                        performanceShowListDTO.setId(performanceEntity.getId());
                        performanceShowListDTO.setPerformanceType(performanceEntity.getPerformanceType());
                        performanceShowListDTO.setPerformanceName(performanceEntity.getPerformanceName());
                        performanceShowListDTO.setScope(scopeMap.get(performanceEntity.getId()));
                        performanceShowListDTO.setPerformanceTime(Arrays.stream(performanceEntity.getPerformanceTime().split(",")).map(PerformanceTimeEnum::valueOf).collect(Collectors.toList()));
                        if (performanceShowListDTO.getPerformanceTime().contains(PerformanceTimeEnum.BEFORE_DUE_DATE)) {
                            performanceShowListDTO.setPerformanceDay(performanceEntity.getPerformanceDay());
                        }
                        performanceShowListDTO.setPerformanceObject(Arrays.stream(performanceEntity.getPerformanceObject().split(",")).map(PerformanceObjectEnum::valueOf).collect(Collectors.toList()));
                        if (performanceShowListDTO.getPerformanceObject().contains(PerformanceObjectEnum.SPECIFIED_PERSON) && employeeShow != null) {
                            List<EmployeeShowVO> showVOS = Arrays.stream(performanceEntity.getPerformanceUser().split(",")).map(Long::valueOf)
                                    .map(employeeShow::get).collect(Collectors.toList());
                            performanceShowListDTO.setPerformanceUser(showVOS);
                        }
                        performanceShowListDTO.setPerformanceMethod(performanceEntity.getPerformanceMethod());
                        return performanceShowListDTO;
                    }).collect(Collectors.toList());
            Page<PerformanceShowListDTO> pageResult = new Page<>();
            BeanUtils.copyProperties(performanceEntityIPage, pageResult);
            pageResult.setRecords(performanceShowListDTOS);

            return SingleResponse.of(pageResult);
        } catch (Exception e) {
            log.error("获取履约提醒列表失败", e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), "获取履约提醒列表失败：" + e.getMessage());
        }
    }
}
